package quirk;

import java.io.IOException;
import java.io.StringReader;

/**
 * This class represents a query passed in by the user. It's really just 
 * a wrapper for a TermList with some info about the allowed query grammar.
 * 
 * @author Andrew Bernard
 */
public class Query {
  private TermList termList;
  
  protected class Result {
    public Index.DataHeader dataHeader;
    public int lineNum;
    public int lineFilter;
    
    public Result(Index.DataHeader dataHeader, int lineNum, int lineFilter) {
      this.dataHeader = dataHeader;
      this.lineNum = lineNum;
      this.lineFilter = lineFilter;
    }
    
    public String toString() {
      return "<" + dataHeader.shortFileName + ", " + lineNum + ">";
    }
  }
  
  /**
   * Constructor. 
   * @param query
   */
  public Query(String query) throws UserInteractionException {
    if(checkGrammar(query))
      termList = new TermList(query.trim());
    else
      throw new UserInteractionException(Constants.ERR_GRAMMAR);
  }
  
  /**
   * Applies the pattern of this query to the mapping of words.
   * For example:<br><br>
   * <pre>
   *    mapping1 = [true] [false] [true]<br>
   *    mapping2 = [true] [false] [false]<br>
   *    <br>
   *    If this object's query pattern was: WORD1 (WORD2 | WORD3)    
   *    then this method would return true for mapping1 and
   *    false for mapping2
   * </pre>   
   * @param mapping   an array of Word objects corresponding to a line in a file 
   * @return the value of this query's pattern applied to the mapping
   */
  public boolean evaluate(QueryWord[] mapping) {
    return termList.evaluate(mapping);
  }
  
  private boolean checkGrammar(String query) {
    int openTermlists = 0;
    int closedTermlists = 0;
    StringReader reader = new StringReader(query);
    try {
      for(int nextChar = reader.read(); nextChar != Constants.EOF; nextChar = reader.read()) {
        if(nextChar == '(')
          openTermlists++;
        else if(nextChar == ')')
          closedTermlists++;
      }
    }
    catch (IOException ex) {
      //if you figure out how this could ever happen, then handle it accordingly
    }
    return openTermlists == closedTermlists;
  }
        
  /** Tests if the character is part of the grammar used to form queries */
  public static boolean isGrammar(int ch) {
    return ch == '(' || ch == ')' || ch == '|' || ch == ' ';    
  }
}
